/*
 * @(#)Digest.java	2016年12月22日上午11:08:52
 * Copyright 2017 All rights reserved.
 */
package com.example.zk.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;

import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class Digest {

	public static final String DIGEST_TYPE_MD5 = "MD5";

	public static final String DIGEST_TYPE_SHA = "SHA-1";

	public static final int HASH_INTERATIONS = 1024;

	public static final int SALT_SIZE = 8;

	public static MessageDigest getMessageDigest(String type) {
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance(type);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return md;
	}
	
	/**
	 * 生成安全的密码，生成随机的16位salt并经过1024次 sha-1 hash
	 * @param plainPassword
	 * @return
	 */
	public static String encryptPassword(String plainPassword) {
		if(StringUtils.isEmpty(plainPassword)) {
			return "";
		}
		String plain = Encodes.unescapeHtml(plainPassword);
		byte[] salt = generateSalt(SALT_SIZE);
		byte[] hashPassword = sha1(plain.getBytes(), salt, HASH_INTERATIONS);
		return Encodes.encodeHex(salt) + Encodes.encodeHex(hashPassword);
	}

	public static String encryptPassword(String plainPassword, String salt) {
		if(StringUtils.isEmpty(plainPassword)) {
			return "";
		}
		String plain = Encodes.unescapeHtml(plainPassword);
		byte[] saltBytes = Encodes.decodeHex(salt);
		byte[] hashPassword = sha1(plain.getBytes(), saltBytes, HASH_INTERATIONS);
		return Encodes.encodeHex(saltBytes) + Encodes.encodeHex(hashPassword);
	}

	/**
	 * md5加密算法
	 * @param data
	 * @return
	 */
	public static String md5(String data) {
		if (StringUtils.isEmpty(data)) {
			return StringUtils.EMPTY;
		}
		return getSecretKey(DIGEST_TYPE_MD5, data);
	}

	/**
	 * SHA加密算法
	 * @param data
	 * @return
	 */
	public static String sha1(String data) {
		if (StringUtils.isEmpty(data)) {
			return StringUtils.EMPTY;
		}
		return getSecretKey(DIGEST_TYPE_SHA, data);
	}

	/**
	 * 获得指定算法的消息摘要
	 * @param algorithm
	 * @param data
	 * @return
	 */
	public static String get(String algorithm, String data) {
		if (StringUtils.isEmpty(data)) {
			return StringUtils.EMPTY;
		}
		return getSecretKey(algorithm, data);
	}

	/**
	 * 生成安全的密钥
	 * @param plainPassword
	 * @return
	 */
	public static String getSaltEncrypt(String plainPassword) {
		if (StringUtils.isEmpty(plainPassword)) {
			return StringUtils.EMPTY;
		}
		String plain = Encodes.unescapeHtml(plainPassword);
		byte[] salt = generateSalt(SALT_SIZE);
		byte[] hashPassword = sha1(plain.getBytes(), salt, HASH_INTERATIONS);
		return Encodes.encodeHex(salt) + Encodes.encodeHex(hashPassword);
	}

	/**
	 * 得到加盐密钥
	 * @param plainPassword
	 * @param salt
	 * @return
	 */
	public static String getSaltEncrypt(String plainPassword, String salt) {
		if (StringUtils.isEmpty(plainPassword)) {
			return "";
		}
		String plain = Encodes.unescapeHtml(plainPassword);
		byte[] saltBytes = Encodes.decodeHex(salt);
		byte[] hashPassword = sha1(plain.getBytes(), saltBytes, HASH_INTERATIONS);
		return Encodes.encodeHex(saltBytes) + Encodes.encodeHex(hashPassword);
	}

	/**
	 * 得到加盐密钥
	 * @param plainPassword
	 * @param salt
	 * @return
	 */
	public static String getSaltEncrypt(String plainPassword, String algorithm, String salt) {
		if (StringUtils.isEmpty(plainPassword)) {
			return "";
		}
		String plain = Encodes.unescapeHtml(plainPassword);
		byte[] saltBytes = Encodes.decodeHex(salt);
		byte[] hashPassword = sha1(plain.getBytes(), algorithm, saltBytes, HASH_INTERATIONS);
		return Encodes.encodeHex(saltBytes) + Encodes.encodeHex(hashPassword);
	}

	private static byte[] sha1(byte[] input, byte[] salt, int iterations) {
		return digest(input, DIGEST_TYPE_SHA, salt, iterations);
	}

	private static byte[] sha1(byte[] input, String algorithm, byte[] salt, int iterations) {
		return digest(input, DIGEST_TYPE_SHA, salt, iterations);
	}

	/**
	 * 生成随机的Byte[]作为salt.
	 * @param numBytes byte数组的大小
	 */
	private static byte[] generateSalt(int numBytes) {
		Validate.isTrue(numBytes > 0, "numBytes argument must be a positive integer (1 or larger)", numBytes);
		byte[] bytes = new byte[numBytes];
		SecureRandom random = new SecureRandom();
		random.nextBytes(bytes);
		return bytes;
	}

	private static String getSecretKey(String algorithm, String data) {
		MessageDigest digest = null;
		try {
			digest = MessageDigest.getInstance(algorithm);
			digest.update(data.getBytes("utf-8"));
			byte[] pass = digest.digest();
			return Encodes.encodeHex(pass);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {

		}
		return null;
	}

	/**
	 * 对字符串进行散列, 支持md5与sha1算法.
	 * @param input
	 * @param algorithm
	 * @param salt
	 * @param iterations
	 * @return
	 */
	private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) {
		byte[] result = null;
		try {
			MessageDigest digest = MessageDigest.getInstance(algorithm);
			if (salt != null) {
				digest.update(salt);
			}
			result = digest.digest(input);
			for (int i = 1; i < iterations; i++) {
				digest.reset();
				result = digest.digest(result);
			}
		} catch (GeneralSecurityException e) {
			e.printStackTrace();
		}
		return result;
	}

    public static void main(String agrs[])throws Exception{
       String ss  ="successMsg=提交成功&id=5704&realname=刘双原&idCardNumber=411212122512115455&image1=http://image.zhi-you.net/1/367a75156be24cbc86c4e183091410d9&image2=http://image.zhi-you.net/1/57044632727346dcbfa4aba357ff8045&gender=0&provinceId=1&cityId=2&districtId=3&type=1&expirationDate=2018-09-28&confirmStatus=3&provinceName=北京市&cityName=市辖区&districtName=东城区&typeName=身份证&genderStr=男&token=2763901f0af34445aa2816d155f4d3ae";
        System.out.println(md5(md5(ss)));  //14e1b600b1fd579f47433b88e8d85291 ,14e1b600b1fd579f47433b88e8d85291
		System.out.println(md5(md5(new String(ss.toString().getBytes("utf-8")))));

    }

}
